package com.eelpo.framework.socket.handler;

import java.nio.ByteBuffer;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

/**
 * 字节流解码，处理黏包问题，跨域策略
 * 
 * @author <a href="mailto:whz-work@163.com">汪洪州</a>
 * 
 * @since 1.0 Create on May 29, 2012
 */
public class SocketFrameDecoder extends FrameDecoder {

	/**
	 * 请求状态(0：未知请求，1：逻辑请求，2：跨域请求)
	 */
	private byte requestStatus = 0;

	/**
	 * 消息体长度
	 */
	private int messageBodySize = 0;

	/**
	 * 请求头长度
	 */
	private static final int HEADER_LENGTH = 4;

	/**
	 * 跨域请求头<policy-file-request/>.
	 */
	private static final int CROSS_DOMAIN_HEADER = ByteBuffer.wrap("<pol".getBytes()).asIntBuffer().get();

	/**
	 * 跨域策略
	 */
	private static final byte[] CROSS_DOMAIN_POLICY = "<cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0".getBytes();

	@Override
	protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
		switch (requestStatus) {
		case 0:
			if (buffer.readableBytes() < HEADER_LENGTH) {
				return null;
			}

			int header = buffer.readInt();
			if (isCrossDomainRequest(header)) {
				requestStatus = 2;
				Channels.write(ctx, Channels.succeededFuture(ctx.getChannel()), ChannelBuffers.wrappedBuffer(CROSS_DOMAIN_POLICY));
			} else {
				requestStatus = 1;
				messageBodySize = header;
			}
		case 1:
			if (buffer.readableBytes() < messageBodySize) {
				return null;
			} else {
				ChannelBuffer frame = buffer.factory().getBuffer(messageBodySize);
				frame.writeBytes(buffer, messageBodySize);
				requestStatus = 0;
				return frame;
			}
		case 2:
			return null;
		default:
			throw new Exception("Request Status Error");
		}
	}

	/**
	 * 检查是否为跨域请求
	 * 
	 * @param header
	 */
	public boolean isCrossDomainRequest(int header) {
		return header == CROSS_DOMAIN_HEADER;
	}
}
